package com.sapuo.enroll.utils;

import org.apache.commons.codec.binary.Base64;
import org.springframework.stereotype.Component;

import javax.crypto.Cipher;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;

/**
 * @Auther: lijunwen
 * @Date: 2020/1/11 11:26
 * @Description:
 */
@Component
public class RsaUtil {

    private static Map<Integer, String> keyMap = new HashMap<Integer, String>();  //用于封装随机产生的公钥与私钥

    /**
     * 随机生成密钥对
     * @throws NoSuchAlgorithmException
     */
    public static void genKeyPair() throws NoSuchAlgorithmException {
        // KeyPairGenerator类用于生成公钥和私钥对，基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对生成器，密钥大小为96-1024位
        keyPairGen.initialize(512,new SecureRandom());
        // 生成一个密钥对，保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥
        String publicKeyString = new String(Base64A.encodeToString(publicKey.getEncoded(), Base64A.DEFAULT));
        // 得到私钥字符串
        String privateKeyString = new String(Base64A.encodeToString(privateKey.getEncoded(),Base64A.DEFAULT));
        // 将公钥和私钥保存到Map
        keyMap.put(0,publicKeyString);  //0表示公钥
        keyMap.put(1,privateKeyString);  //1表示私钥
    }
    /**
     * RSA公钥加密
     *
     * @param str
     *            加密字符串
     * @param publicKey
     *            公钥
     * @param urlSafe url安全
     * @return 密文
     * @throws Exception
     *             加密过程中的异常信息
     */
    public static String encrypt( String str, String publicKey, boolean urlSafe ) throws Exception{
        //base64编码的公钥
        byte[] decoded = Base64A.decode(publicKey,Base64A.DEFAULT);
        RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
        //RSA加密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] bdata=cipher.doFinal(str.getBytes("UTF-8"));

        return Base64A.encodeToString(bdata,Base64A.DEFAULT);
    }

    /**
     * RSA私钥解密
     *
     * @param str
     *            加密字符串
     * @param privateKey
     *            私钥
     * @return 铭文
     * @throws Exception
     *             解密过程中的异常信息
     */
    public static String decrypt(String str, String privateKey) throws Exception{
        //64位解码加密后的字符串
        byte[] inputByte = Base64A.decode(str,Base64A.DEFAULT);
        //base64编码的私钥
        byte[] decoded = Base64A.decode(privateKey,Base64A.DEFAULT);
        RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
        //RSA解密
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        return new String(cipher.doFinal(inputByte));
    }

    /**
     * 根据key进行排序
     * @param map
     * @return a=&b=...
     */
    public static String getSignToken(Map<String, String> map) {
        List<Map.Entry<String, String>> infoIds = new ArrayList<>(map.entrySet());
        // 对所有传入参数按照字段名的 ASCII 码从小到大排序（字典序）
        Collections.sort(infoIds, new Comparator<Map.Entry<String, String>>() {
            @Override
            public int compare(Map.Entry<String, String> o1, Map.Entry<String, String> o2) {
                return o1.getKey().compareTo(o2.getKey());
            }
        });
        // 构造签名键值对的格式
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> item : infoIds) {
            String key = item.getKey();
            String val = item.getValue();
            sb.append(key + "=" + val + "&");
        }
        return sb.toString().substring(0,sb.length()-1);
    }

    public static void main(String[] args) throws Exception{

//        genKeyPair();
//        System.out.println(keyMap.get(0));  //0表示公钥
//        System.out.println(keyMap.get(1));  //0表示公钥


        String a = "fmlCHAISfWqiXxXQu0WotBqw3Cjm0ee4whihzZiQL8lQXrQN92cSgPaxnTBeNCfvsIIC01fSgCOUjTAqW+WbJQ==";

        String RSA_PUBLIC_KEY_1024B = "MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAIGcakQhmIK181wjhozfiY6rY5hu7Cb/+YHg3Y25XZKUnCfxlCO6hcj56GN53rf5h8AxKiieRZgxXA+pf8KCpisCAwEAAQ==";
        String RSA_PRIVATE_KEY_1024B = "MIIBUwIBADANBgkqhkiG9w0BAQEFAASCAT0wggE5AgEAAkEAgZxqRCGYgrXzXCOGjN+JjqtjmG7sJv/5geDdjbldkpScJ/GUI7qFyPnoY3net/mHwDEqKJ5FmDFcD6l/woKmKwIDAQABAkAnLgRFki5LHPty195diVlIwnB57NYAOBLRewseQ3GQ1GLJIZp7btHH25UaDL2sHX4K1QR39p25kN8kxAIzf9ahAiEAy9DBEdDDqptL/p6z9vOrRuvOJIsDZrTKaFw/abesJxsCIQCiy98DqTp5jlhRTi0KUomJsXhxYuYRhxd/ZMFqB44eMQIgS+3OL3PloQZPzmCTTNnEIhyw5F5Bex65FR3gpeK+KKcCIHm9faOuPKVENnVuwa3TdTj79zbLn4MCBCdnQGA7ECMxAiATh0mPducLESEsV1z0S49GUWY8zblM6ucsgTgkdrOu9Q==";
        String signStr = "15801685807";
        String encryptData = encrypt(signStr, RSA_PUBLIC_KEY_1024B, true);
        System.out.println(encryptData);
        System.out.println(decrypt(encryptData, RSA_PRIVATE_KEY_1024B));
    }
}
